import { Controller, Post, Body, Get, Request, BadRequestException, HttpStatus } from '@nestjs/common'
import { ApiTags, ApiOperation, ApiBody, ApiBearerAuth } from '@nestjs/swagger'
import { AuthService } from '../services/auth.service'
import { LoginDto } from '../dto/login.dto'
import { RegisterDto } from '../dto/register.dto'
import * as svgCaptcha from 'svg-captcha'
import { v4 as uuidv4 } from 'uuid'
import { CACHE_MANAGER } from '@nestjs/cache-manager'
import { Inject } from '@nestjs/common'
import { Cache } from 'cache-manager'
import { Public } from 'src/common/decorators/public.decorator'
import { LoginPayload, Payload } from 'src/common/interfaces/auth.interface'
import { Permissions } from 'src/common/decorators/permissions.decorator'
import { Response } from 'src/common/interfaces/common'
import { ConfigService as SystemConfigService } from 'src/modules/config/services/config.service'

/**
 * 认证相关接口
 */
@ApiTags('认证')
@Controller('auth')
export class AuthController {
  constructor(
    private readonly authService: AuthService,
    @Inject(CACHE_MANAGER) private cacheManager: Cache,
    private readonly systemConfigService: SystemConfigService,
  ) {}

  /**
   * 获取图形验证码
   * @returns svg和唯一id
   */
  @Get('captcha')
  @ApiOperation({ summary: '获取图形验证码' })
  @Public()
  async getCaptcha() {
    const captcha = svgCaptcha.create({
      size: 4,
      noise: 2,
      color: true,
      background: '#c2c2c2',
    })
    const captchaId = uuidv4()
    // 验证码内容存入缓存，5分钟有效
    await this.cacheManager.set(`captcha:${captchaId}`, captcha.text, 300000)
    return { captchaId, image: captcha.data }
  }

  /**
   * 用户登录
   * @param dto 登录信息
   * @returns JWT token 和用户信息
   */
  @Post('login')
  @ApiOperation({ summary: '用户登录' })
  @ApiBody({ type: LoginDto })
  @Public()
  async login(@Body() dto: LoginDto): Promise<Response<LoginPayload>> {
    // 检查验证码是否启用
    const captchaEnabled = await this.systemConfigService.getConfig<boolean>('captcha.enabled', true)

    // 如果启用了验证码，则校验验证码
    if (captchaEnabled) {
      const cacheKey = `captcha:${dto.captchaId}`
      const realCaptcha = await this.cacheManager.get<string>(cacheKey)
      if (!realCaptcha || realCaptcha.toLowerCase() !== dto.captcha.toLowerCase()) {
        throw new BadRequestException('验证码错误或已过期')
      }
      await this.cacheManager.del(cacheKey) // 验证码只用一次
    }

    const result = await this.authService.login(dto)
    return {
      statusCode: HttpStatus.OK,
      message: '登录成功',
      data: result,
    }
  }

  /**
   * 刷新AccessToken
   * @param refresh_token refresh_token字符串
   * @returns 新的access_token
   */
  @Post('refresh')
  @ApiOperation({ summary: '刷新AccessToken' })
  @ApiBody({ schema: { properties: { refresh_token: { type: 'string' } } } })
  @Public()
  async refresh(@Body('refresh_token') refreshToken: string): Promise<Response<{ access_token: string }>> {
    return {
      statusCode: HttpStatus.OK,
      message: '刷新成功',
      data: { access_token: await this.authService.refresh(refreshToken) },
    }
  }

  /**
   * 用户注册
   * @param dto 注册信息
   * @returns 注册结果
   */
  @Post('register')
  @ApiOperation({ summary: '用户注册' })
  @ApiBody({ type: RegisterDto })
  @Public()
  async register(@Body() dto: RegisterDto) {
    // 检查验证码是否启用
    const captchaEnabled = await this.systemConfigService.getConfig<boolean>('captcha.enabled', true)

    // 如果启用了验证码，则验证验证码
    if (captchaEnabled) {
      const cacheCaptcha = await this.cacheManager.get<string>(`captcha:${dto.captchaId}`)
      if (!cacheCaptcha || cacheCaptcha.toLowerCase() !== dto.captcha.toLowerCase()) {
        throw new BadRequestException('验证码错误或已失效')
      }
      // 删除验证码，防止重复使用
      await this.cacheManager.del(`captcha:${dto.captchaId}`)
    }

    // 执行注册逻辑
    const result = await this.authService.register(dto)
    return {
      code: 1,
      message: '注册成功',
      data: result,
    }
  }

  /**
   * 获取当前登录用户信息
   * @param req 请求对象，包含user
   * @returns 用户信息
   */
  @Get('profile')
  @ApiOperation({ summary: '获取当前用户信息' })
  @ApiBearerAuth()
  @Permissions('auth:profile')
  async profile(@Request() req: { user: Payload } & Request) {
    return this.authService.getProfile(req.user.id)
  }

  /**
   * 获取当前登录用户信息，包括role和permission
   * @param req 请求对象，包含user
   * @returns 用户信息，包括role和permission
   */
  @Get('userinfo')
  @ApiOperation({ summary: '获取当前登录用户信息，包括role和permission' })
  @ApiBearerAuth()
  @Permissions('auth:userinfo')
  async userInfo(@Request() req: { user: Payload } & Request) {
    return this.authService.getUserInfo(req.user.id)
  }
}
